

// 变量声明

{
    let a = 10; // a只在块内有效
    var b = 1; // 全局有效，不建议使用
}

// 块作用域导致的for循环变量值变化
for(let i = 0;i<2;i++){
    let i = 'abc';
    console.log(i); // for循环的i是父作用域
}

/* 暂时性死区（temporal dead zone,TDZ）
   1. 不存在变量提升
   2. 一进入当前作用域，变量就已经存在，但是不可获取，只有等到申明变量那一行才能获取
 */

try{
    function bar(x=y,y=2) {
        return 1;
    }
    bar();
}catch (ReferenceError) {
    console.log('x赋值时y未定义')
}

try{
    console.log(a1);
    let a1 = 1;
}catch (ReferenceError) {
    console.log('let定义的变量,不存在变量提升')
}

// 不允许重复声明

let a = 1;
// let a = 3;

// typeof不再绝对安全
try{
    typeof x1;
}catch (ReferenceError) {
    console.log('变量未定义，typeof异常')
}

// 块级作用域，允许任意嵌套

function f1() {
    let n = 5;
    if(true){
        let n = 10;
    }
    console.log('f1:'+n);
}
f1();

/* 块级作用域针对es6浏览器和nodejs，为了兼容老代码，行为修改
   1. 允许在块内作用域声明函数
   2. 函数声明类似var，提升到全局作用域或函数作用域头部
   3. 函数声明还会提升到所在块作用域的头部
   4. 尽量使用函数表达式
 */

function f2() {
    console.log('I am outside.');
}
(function () {
    if (false){
        function f2() {
            console.log('I am inside.');
        }
    }
    console.log(f2); // 输出：undefined，
})();


/*
  双冒号运算符
 */
var a3 = 5;
var o3 = {
    a3:10
};
function b3() {
    console.log(this.a3);
}
console.log(b3.bind(o3));
console.log(b3.bind(o3)());
o3::b3;

